﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Phone.Controls.Maps;
using Microsoft.Phone.Controls.Maps.Platform;
using RutoDeBared.geocodeservice;
using System.Device.Location;
using System.Windows.Shapes;
using System.Windows.Media;
using System.Windows.Controls;
using System.Resources;
using System.Windows.Threading;


namespace RutoDeBared.Control
{
    class Navigatie
    {
        internal geocodeservice.GeocodeResult[] geocodeResults;
        Location location = new Location();

        private int hoek;

        static List<Location> routeplanning = new List<Location>();

        GeoCoordinate huidigeLocatie;
        HuidigeLocatie hl = new HuidigeLocatie();
        Boolean completed = false;



        public Navigatie()
        {
        }

        public int gethoek()
        {
            hoek = hl.getHoek();
            return hoek;
        }

        public void routeplanningVerwijderen()
        {
            routeplanning.Clear();
            completed = false;
        }

        public List<Location> routeplanningOpvragen()
        {
            return routeplanning;
        }


        public GeoCoordinate getHuidigeLocatie()
        {
            huidigeLocatie = hl.getHuidigeLocatie();
            
            //TODO EDIT
            //huidigeLocatie = new GeoCoordinate(51.6410202, 4.8616901);
            return huidigeLocatie;
        }

        public void routePlannen(List<GeoCoordinate> l)
        {
            completed = false;
            //lijst invoeren punt voor punt 25 max?
            int x = 0;

            geocodeResults = new geocodeservice.GeocodeResult[l.Count];
            if (l.Count > 0)
            {
                foreach (GeoCoordinate g in l)
                {
                    Geocode(l[x].Latitude + "," + l[x].Longitude, x);
                    x++;
                }
            }
        }

        private void Geocode(string strAddress, int waypointIndex)
        {
            // Here we create the service variable and set the callback method using the GeocodeCompleted property.
            RutoDeBared.geocodeservice.GeocodeServiceClient geocodeService = new RutoDeBared.geocodeservice.GeocodeServiceClient("BasicHttpBinding_IGeocodeService");
            geocodeService.GeocodeCompleted += new EventHandler<RutoDeBared.geocodeservice.GeocodeCompletedEventArgs>(geocodeService_GeocodeCompleted);
            // Here we Set the credentials and the geocode query,which could be an address or location.
            RutoDeBared.geocodeservice.GeocodeRequest geocodeRequest = new RutoDeBared.geocodeservice.GeocodeRequest();
            geocodeRequest.Credentials = new Credentials();
            geocodeRequest.Credentials.ApplicationId = "AkJtUh7B5ps44tFVuNqZ6yCfohMlKlKzeNmhJJMOFF3ZA0N5biKKCVdmGxuG-Xzo";
            geocodeRequest.Query = strAddress;
            // Now Making the asynchronous Geocode request, using the 'waypoint index' as
            //   the user state to track this request and allow it to be identified when the response is returned.
            geocodeService.GeocodeAsync(geocodeRequest, waypointIndex);
        }

        private void geocodeService_GeocodeCompleted(object sender, geocodeservice.GeocodeCompletedEventArgs e)
        {
            // Retrieve the user state of this response (the 'waypoint index') to identify which geocode request it corresponds to
            int waypointIndex = System.Convert.ToInt32(e.UserState);
            // Retrieve the GeocodeResult for this response and store it in the global variable geocodeResults, using
            //   the waypoint index to position it in the array.
            try
            {
                geocodeResults[waypointIndex] = e.Result.Results[0];
            }
            catch (Exception)
            {

            }
            // Look at each element in the global gecodeResults array to figure out if more geocode responses still
            //   need to be returned.
            bool doneGeocoding = true;
            foreach (geocodeservice.GeocodeResult gr in geocodeResults)
            {
                if (gr == null)
                {
                    doneGeocoding = false;
                }
            }
            // If the geocodeResults array is totally filled, then calculate the route.
            if (doneGeocoding)
                CalculateRoute(geocodeResults);
            

        }

        private void CalculateRoute(geocodeservice.GeocodeResult[] results)
        {
            routeservice.RouteServiceClient routeService = new routeservice.RouteServiceClient("BasicHttpBinding_IRouteService");
            routeService.CalculateRouteCompleted += new EventHandler<routeservice.CalculateRouteCompletedEventArgs>(routeService_CalculateRouteCompleted);          // Set the token.
            routeservice.RouteRequest routeRequest = new routeservice.RouteRequest();
            routeRequest.Credentials = new Credentials();
            routeRequest.Credentials.ApplicationId = "AkJtUh7B5ps44tFVuNqZ6yCfohMlKlKzeNmhJJMOFF3ZA0N5biKKCVdmGxuG-Xzo";
            // Return the route points so the route can be drawn.
            routeRequest.Options = new routeservice.RouteOptions();
            routeRequest.Options.RoutePathType = routeservice.RoutePathType.Points;
            routeRequest.Options.Mode = routeservice.TravelMode.Walking;
            

            // Set the waypoints of the route to be calculated using the Geocode Service results stored in the geocodeResults variable.
            routeRequest.Waypoints = new System.Collections.ObjectModel.ObservableCollection<routeservice.Waypoint>();
            foreach (geocodeservice.GeocodeResult result in results)
            {
                routeRequest.Waypoints.Add(GeocodeResultToWaypoint(result));        
            }
            // Make the CalculateRoute asnychronous request.
            routeService.CalculateRouteAsync(routeRequest);
        }

        private routeservice.Waypoint GeocodeResultToWaypoint(geocodeservice.GeocodeResult result)
        {
            routeservice.Waypoint waypoint = new routeservice.Waypoint();
            waypoint.Description = result.DisplayName;
            waypoint.Location = new Location();
            waypoint.Location.Latitude = result.Locations[0].Latitude;
            waypoint.Location.Longitude = result.Locations[0].Longitude;
            return waypoint;
        }

        private void routeService_CalculateRouteCompleted(object sender, routeservice.CalculateRouteCompletedEventArgs e)
        {
            routeplanning.Clear();
            // If the route calculate was a success and contains a route, then draw the route on the map.
            if ((e.Result.ResponseSummary.StatusCode == routeservice.ResponseStatusCode.Success) & (e.Result.Result.Legs.Count != 0))
            {
                // Retrieve the route points that define the shape of the route.
                foreach (Location p in e.Result.Result.RoutePath.Points)
                {
                    routeplanning.Add(new Location { Latitude = p.Latitude, Longitude = p.Longitude });
                }
            }
            completed = true;
        }

        public Boolean routeklaar()
        {
            return completed;
        }
    }
}
